static guint gtk_rc_parse_style (GtkRcContext *context,
GScanner *scanner);
static guint gtk_rc_parse_assignment (GScanner *scanner,
+ GtkRcStyle *style,
GtkRcProperty *prop);
static guint gtk_rc_parse_bg (GScanner *scanner,
GtkRcStyle *style);
* Parsing functions *
*********************/
+static gboolean
+lookup_color (GtkRcStyle *style,
+ const char *color_name,
+ GdkColor *color)
+{
+ GtkRcStylePrivate *priv = GTK_RC_STYLE_GET_PRIVATE (style);
+ GSList *iter;
+
+ for (iter = priv->color_hashes; iter != NULL; iter = iter->next)
+ {
+ GHashTable *hash = iter->data;
+ GdkColor *match = g_hash_table_lookup (hash, color_name);
+
+ if (match)
+ {
+ color->red = match->red;
+ color->green = match->green;
+ color->blue = match->blue;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static guint
-rc_parse_token_or_compound (GScanner *scanner,
- GString *gstring,
- GTokenType delimiter)
+rc_parse_token_or_compound (GScanner *scanner,
+ GtkRcStyle *style,
+ GString *gstring,
+ GTokenType delimiter)
{
guint token = g_scanner_get_next_token (scanner);
break;
case G_TOKEN_COMMENT_SINGLE:
case G_TOKEN_COMMENT_MULTI:
- return rc_parse_token_or_compound (scanner, gstring, delimiter);
+ return rc_parse_token_or_compound (scanner, style, gstring, delimiter);
case G_TOKEN_LEFT_PAREN:
g_string_append_c (gstring, ' ');
g_string_append_c (gstring, token);
- token = rc_parse_token_or_compound (scanner, gstring, G_TOKEN_RIGHT_PAREN);
+ token = rc_parse_token_or_compound (scanner, style, gstring, G_TOKEN_RIGHT_PAREN);
if (token != G_TOKEN_NONE)
return token;
break;
case G_TOKEN_LEFT_CURLY:
g_string_append_c (gstring, ' ');
g_string_append_c (gstring, token);
- token = rc_parse_token_or_compound (scanner, gstring, G_TOKEN_RIGHT_CURLY);
+ token = rc_parse_token_or_compound (scanner, style, gstring, G_TOKEN_RIGHT_CURLY);
if (token != G_TOKEN_NONE)
return token;
break;
case G_TOKEN_LEFT_BRACE:
g_string_append_c (gstring, ' ');
g_string_append_c (gstring, token);
- token = rc_parse_token_or_compound (scanner, gstring, G_TOKEN_RIGHT_BRACE);
+ token = rc_parse_token_or_compound (scanner, style, gstring, G_TOKEN_RIGHT_BRACE);
if (token != G_TOKEN_NONE)
return token;
break;
+ case '@':
+ if (g_scanner_peek_next_token (scanner) == G_TOKEN_IDENTIFIER)
+ {
+ GdkColor color;
+
+ g_scanner_get_next_token (scanner);
+
+ if (!style || !lookup_color (style, scanner->value.v_identifier,
+ &color))
+ {
+ g_scanner_warn (scanner, "Invalid symbolic color '%s'",
+ scanner->value.v_identifier);
+ return G_TOKEN_IDENTIFIER;
+ }
+
+ g_string_append_printf (gstring, " { %0.4f, %0.4f, %0.4f }",
+ (gdouble) color.red / 65535.0,
+ (gdouble) color.green / 65535.0,
+ (gdouble) color.blue / 65535.0);
+ break;
+ }
+ else
+ return G_TOKEN_IDENTIFIER;
default:
if (token >= 256 || token < 1)
return delimiter ? delimiter : G_TOKEN_STRING;
if (!delimiter)
return G_TOKEN_NONE;
else
- return rc_parse_token_or_compound (scanner, gstring, delimiter);
+ return rc_parse_token_or_compound (scanner, style, gstring, delimiter);
}
static guint
gtk_rc_parse_assignment (GScanner *scanner,
+ GtkRcStyle *style,
GtkRcProperty *prop)
{
gboolean scan_identifier = scanner->config->scan_identifier;
gboolean scan_identifier_NULL = scanner->config->scan_identifier_NULL;
gboolean numbers_2_int = scanner->config->numbers_2_int;
gboolean negate = FALSE;
- guint token;
+ gboolean is_color = FALSE;
+ guint token;
/* check that this is an assignment */
if (g_scanner_get_next_token (scanner) != '=')
else
prop->origin = NULL;
+ /* parse optional symbolic color prefix */
+ if (g_scanner_peek_next_token (scanner) == '@')
+ {
+ g_scanner_get_next_token (scanner); /* eat color prefix */
+ is_color = TRUE;
+ }
+
/* parse optional sign */
- if (g_scanner_peek_next_token (scanner) == '-')
+ if (!is_color && g_scanner_peek_next_token (scanner) == '-')
{
g_scanner_get_next_token (scanner); /* eat sign */
negate = TRUE;
}
- /* parse one of LONG, DOUBLE and STRING or, if that fails, create an unparsed compund */
+ /* parse one of LONG, DOUBLE and STRING or, if that fails, create an
+ * unparsed compund
+ */
token = g_scanner_peek_next_token (scanner);
+
+ if (is_color && token != G_TOKEN_IDENTIFIER)
+ {
+ token = G_TOKEN_IDENTIFIER;
+ goto out;
+ }
+
switch (token)
{
case G_TOKEN_INT:
}
break;
case G_TOKEN_IDENTIFIER:
+ if (is_color)
+ {
+ GdkColor color;
+ GString *gstring;
+
+ g_scanner_get_next_token (scanner);
+
+ if (!style || !lookup_color (style, scanner->value.v_identifier,
+ &color))
+ {
+ g_scanner_warn (scanner, "Invalid symbolic color '%s'",
+ scanner->value.v_identifier);
+ token = G_TOKEN_IDENTIFIER;
+ break;
+ }
+
+ gstring = g_string_new (NULL);
+
+ g_string_append_printf (gstring, " { %0.4f, %0.4f, %0.4f } ",
+ (gdouble) color.red / 65535.0,
+ (gdouble) color.green / 65535.0,
+ (gdouble) color.blue / 65535.0);
+
+ g_value_init (&prop->value, G_TYPE_GSTRING);
+ g_value_take_boxed (&prop->value, gstring);
+ token = G_TOKEN_NONE;
+ break;
+ }
+ /* fall through */
case G_TOKEN_LEFT_PAREN:
case G_TOKEN_LEFT_CURLY:
case G_TOKEN_LEFT_BRACE:
if (!negate)
{
- GString *gstring = g_string_new (NULL);
+ GString *gstring = g_string_new (NULL);
+ gboolean parse_on = TRUE;
+
+ /* allow identifier(foobar) to support color expressions */
+ if (token == G_TOKEN_IDENTIFIER)
+ {
+ g_scanner_get_next_token (scanner);
+
+ g_string_append_c (gstring, ' ');
+ g_string_append (gstring, scanner->value.v_identifier);
+
+ token = g_scanner_peek_next_token (scanner);
+
+ if (token != G_TOKEN_LEFT_PAREN)
+ {
+ token = G_TOKEN_NONE;
+ parse_on = FALSE;
+ }
+ }
+
+ if (parse_on)
+ token = rc_parse_token_or_compound (scanner, style, gstring, 0);
- token = rc_parse_token_or_compound (scanner, gstring, 0);
if (token == G_TOKEN_NONE)
{
g_string_append_c (gstring, ' ');
break;
}
+ out:
+
/* restore scanner mode */
scanner->config->scan_identifier = scan_identifier;
scanner->config->scan_symbols = scan_symbols;
g_scanner_get_next_token (scanner); /* eat identifier */
name = g_strdup (scanner->value.v_identifier);
- token = gtk_rc_parse_assignment (scanner, &prop);
+ token = gtk_rc_parse_assignment (scanner, NULL, &prop);
if (token == G_TOKEN_NONE)
{
GtkSettingsValue svalue;
prop.property_name = g_quark_from_string (name);
g_free (name);
- token = gtk_rc_parse_assignment (scanner, &prop);
+ token = gtk_rc_parse_assignment (scanner, rc_style, &prop);
if (token == G_TOKEN_NONE)
{
g_return_val_if_fail (G_VALUE_TYPE (&prop.value) != 0, G_TOKEN_ERROR);
return G_TOKEN_NONE;
}
-static gboolean
-lookup_color (GtkRcStyle *style,
- const char *color_name,
- GdkColor *color)
-{
- GtkRcStylePrivate *priv = GTK_RC_STYLE_GET_PRIVATE (style);
- GSList *iter;
-
- for (iter = priv->color_hashes; iter != NULL; iter = iter->next)
- {
- GHashTable *hash = iter->data;
- GdkColor *match = g_hash_table_lookup (hash, color_name);
-
- if (match)
- {
- color->red = match->red;
- color->green = match->green;
- color->blue = match->blue;
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
guint
gtk_rc_parse_color (GScanner *scanner,
GdkColor *color)